import os
import re
import sys
from pathlib import Path


def read_file(file_path):
    """读取文件内容并返回"""
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            return f.read()
    except Exception as e:
        print(f"无法读取文件 {file_path}: {e}")
        return ""


def process_includes(content, processed_files, base_dir):
    """处理文件中的#include指令"""
    lines = content.split('\n')

    processed_content = []
    include_pattern = re.compile(r'^\s*#include\s+["<](.+?)[">]')

    for line in lines:
        match = include_pattern.search(line)

        if match:
            # 处理 include 行
            include_file = match.group(1)

            # 处理本地包含文件（使用双引号的）
            if line.strip().startswith('#include "'):
                # 构建包含文件的完整路径
                include_path = os.path.join(base_dir, include_file)
                # 如果文件存在且尚未处理
                # print(f"{include_path=}")
                if os.path.exists(include_path) and (include_path not in processed_files):
                    processed_files.append(include_path)

                    include_content = read_file(include_path)
                    processed_include = process_includes(
                        include_content, processed_files, base_dir)

                    processed_content.append(f"\n// 开始包含文件: {include_file}")
                    processed_content.append(processed_include)
                    processed_content.append(f"// 结束包含文件: {include_file}\n")
                    print(f"Process include {line=} 开始包含文件")
            else:
                # 系统头文件（使用尖括号的），保留原include行
                processed_content.append(line)

        elif line.strip().startswith('#pragma'):
            # 处理编译命令，直接忽略
            continue

        elif not bool(line):
            # 空行
            continue

        else:
            # 非include行，直接添加
            processed_content.append(line)

    return '\n'.join(processed_content)


def generate_file_header(input_files, output_file):
    """生成合并文件的头部注释"""
    header =f"""// 合并文件: {os.path.basename(output_file)}"""
    """// 由多个C++文件合并而成\n"""
    f"""// 合并时间: {os.popen('date').read().strip()}\n"""

    for file in input_files:
        header += f"//   - {os.path.basename(file)}\n"
    return header


def merge_cpp_files(source_files, output_file, base_dir=None):
    """将多个C++文件合并为一个文件"""

    # 如果未指定base_dir，使用输出文件所在目录或当前目录
    base_dir = os.getcwd()

    # 已处理的文件集合，避免重复包含
    processed_files = list()
    content = ''

    content += generate_file_header(source_files, output_file)

    # 处理每个源文件
    for file_path in source_files:
        if not os.path.exists(file_path):
            continue

        content += f"\n\n// 开始文件: {os.path.basename(file_path)}\n"

        processed_files.append(os.path.join(base_dir, file_path))
        print(os.path.join(base_dir, file_path))

        content += process_includes(
            read_file(file_path), processed_files, base_dir)

        content += f"\n// 结束文件: {os.path.basename(file_path)}\n"

    try:
        with open(output_file, 'w', encoding='utf-8') as f:
            f.write(content)

        print(f"合并完成，输出文件: {output_file}")
    except Exception as e:
        print(f"写入文件失败: {e}")


def main():
    """主函数"""
    import argparse

    parser = argparse.ArgumentParser(description='将多个C++文件合并为一个源文件')
    parser.add_argument('-o', '--output', required=True, help='输出文件路径')
    parser.add_argument('files', nargs='+', help='要合并的C++源文件和头文件')

    args = parser.parse_args()

    # 检查输出文件是否是.cpp或.c扩展名
    output_ext = os.path.splitext(args.output)[1].lower()
    if output_ext not in ['.cpp', '.c']:
        print(f"警告: 输出文件扩展名 '{output_ext}' 不是标准的C++源文件扩展名 (.cpp/.c)")

    # 合并文件
    merge_cpp_files(args.files, args.output)


if __name__ == "__main__":
    main()
